﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;
namespace BIN
{
    public class ProgStatus
    {
        public string SvcName { get; set; }
        public bool Runned { get; set; }
        public ProgStatus(string svcName, bool runned)
        {
            this.SvcName = svcName;
            this.Runned = runned;
        }
    }
    public class WinServiceOp:IDisposable
    {
        private bool _headSyncRunned = false;
        private List<WinServiceName> OpServiceLst = null;
        private List<string> NeedStopServiceName = null;
        private ServiceController[] AllServices = null;
        public void Dispose()
        {
            if (null != AllServices) AllServices = null;
            if (null != NeedStopServiceName) NeedStopServiceName = null;
            if (null != OpServiceLst) OpServiceLst = null;
        }
        ~WinServiceOp()
        {
            this.Dispose();
        }
        public delegate void ServiceStatusChangeHandler(object sender, ServiceEventArgs e);
        public event ServiceStatusChangeHandler OnServiceStatusChanged;
        public WinServiceOp()
        {
            Init();
        }
        private void Init()
        {
            NeedStopServiceName = new List<string>();
            OpServiceLst = new List<WinServiceName>();
            //同步服务的更新文件
            WinServiceName service =
                new WinServiceName("YSSYNC", @"SYNC\Sync.exe" ,
                    new string[] 
                    {
                    @"SYNC\EntityData.dll",
                    @"SYNC\Sync.exe" ,
                    @"SYNC\ClientSyn.dll" });
            OpServiceLst.Add(service);
            service = new WinServiceName("headSync", @"HEADSYNC\ClientSync.exe",
                new string[] 
                {
                 @"HEADSYNC\ClientSync.exe"
                });
            OpServiceLst.Add(service);
            AllServices = ServiceController.GetServices();
        }
        private bool ArrayHasElement(string[] Arr, string ele)
        {
            if (null == Arr) return false;
            int Len = Arr.Length;
            for (int i = 0; i < Len; i++)
            {
                if (string.Compare(Arr[i].Trim(), ele.Trim(), true) == 0) return true;
            }
            return false;
        }
        private string GetFileRelationService(string FileName)
        {
            foreach (WinServiceName obj in this.OpServiceLst)
            {
                if (string.Compare(obj.ExecFileName, FileName, true) == 0)
                    return obj.ServiceName;
                if (ArrayHasElement(obj.RelationFile, FileName))
                    return obj.ServiceName;
            }
            return "";
        }
        private ServiceController GetServiceControl(string ServiceName)
        {
            int Len = AllServices.Length;
            for (int i = 0; i < Len; i++)
            { 
               if(string.Compare(AllServices[i].ServiceName,ServiceName,true )==0)
                {
                    return AllServices[i];
                }
            }
            return null;
        }
        public ServiceController GetServiceControlCurr(string ServiceName)
        {
            ServiceController ctl = null;
            try
            {
               ctl=  new ServiceController(ServiceName);
               string svcName = ctl.ServiceName;
            }
            catch 
            {
                ctl = null;
            }
            return ctl;
        }
        private void StopService(string serviceName)
        {
            System.ServiceProcess.ServiceController service =
                    GetServiceControlCurr(serviceName);
            if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running  )
            {
                service.Stop();
                for (int i = 0; i < 60; i++)
                {
                    service.Refresh();
                    System.Threading.Thread.Sleep(1000);
                    if (service.Status ==
                        System.ServiceProcess.ServiceControllerStatus.Stopped) break;
                    if (i == 59)
                    {
                        throw new Exception(
                            string.Format("Stop [{0}] failture!", serviceName)
                            );
                    }
                }
            }
            if (null != OnServiceStatusChanged)
            {
                OnServiceStatusChanged(this,
                    new ServiceEventArgs(service.ServiceName,
                        service.DisplayName, 
                        service.Status== ServiceControllerStatus.Stopped?SERVICE_STATUS.STOP: SERVICE_STATUS.START  ));
            }
        }
        private void StartService(string serviceName)
        {
            if ("headSync".Equals(serviceName) && _headSyncRunned ) //特殊处理启动程序
            {
                string Appdir=ShareMet.GetAppDir();
                string fileName = ShareMet.CombineDir(Appdir,
                   @"HEADSYNC\ClientSync.exe");
                if (ShareMet.FileExists(fileName))
                {
                    try
                    {
                        ShareMet.BeginProcess(fileName, Appdir);
                    }
                    catch { }
                }
                return;
            }
            System.ServiceProcess.ServiceController service =
        new System.ServiceProcess.ServiceController(serviceName);
            if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running
                && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
            {
                service.Start();
                for (int i = 0; i < 60; i++)
                {
                    service.Refresh();
                    System.Threading.Thread.Sleep(1000);
                    if (service.Status ==
                        System.ServiceProcess.ServiceControllerStatus.Running) break;
                    if (i == 59)
                    {
                        throw new Exception(
                          string.Format(
                          "Start service [{0}] failture!", serviceName));
                    }
                }
            }
            if (null != OnServiceStatusChanged)
            {
                OnServiceStatusChanged(this,
                    new ServiceEventArgs(service.ServiceName,
                        service.DisplayName,
                        service.Status == ServiceControllerStatus.Stopped ? SERVICE_STATUS.STOP : SERVICE_STATUS.START));
            }
        }
        public void StopService()
        {
            if (null == NeedStopServiceName || NeedStopServiceName.Count == 0) return;
            int count = NeedStopServiceName.Count;
            for (int i = 0; i < count; i++)
            {
                if (NeedStopServiceName[i] == "YSSYNC")
                {
                    ShareMet.ProgRunned("Sync.exe", true);
                }
            }
            System.Threading.Thread.Sleep(500);
        }
        public void StartService()
        {
            if (null == NeedStopServiceName) NeedStopServiceName = new List<string>();
            if (null == NeedStopServiceName || NeedStopServiceName.Count == 0) return;
            int count = NeedStopServiceName.Count;
            for (int i = 0; i < count; i++)
            {
                try
                {
                    StartService(NeedStopServiceName[i]);
                }
                catch { }
            }
        }
        public void CheckFile(string FileName)
        {
            string serviceName = GetFileRelationService(FileName);
            if (string.IsNullOrEmpty( serviceName)) return;
            if ("headSync".Equals(serviceName))
            {
                NeedStopServiceName.Add(serviceName);
            }
            else
            {
                ServiceController ctl = GetServiceControlCurr(serviceName);
                if (null == ctl) return;
                if (ctl.Status == ServiceControllerStatus.Running ||
                    ctl.Status == ServiceControllerStatus.StartPending)
                {
                    if (!NeedStopServiceName.Contains(serviceName))
                    {
                        NeedStopServiceName.Add(serviceName);
                    }
                }
            }
        }
    }
}
